package pers.cz.logtail.util;

import org.apache.commons.io.input.ReversedLinesFileReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pers.cz.jefconfig.config.JefConfiguration;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Stack;
import java.util.TimeZone;

/**
 * @program: PostGirl-panent
 * @description: 文件处理助手
 * @author: Cheng Zhi
 * @create: 2022-10-04 12:38
 **/
public class FileUtils {

    private static Logger logger = LoggerFactory.getLogger(FileUtils.class);
    /**
     * 获取文件总行数
     * @param file
     * @return
     */
    public static long getFileLineCount(File file) {

        long lines= 0;
        try {
            //lines = Files.lines(Paths.get(file.getPath()), Charset.forName("utf-8")).count();

            FileReader fileReader = new FileReader(file);
            LineNumberReader lineNumberReader = new LineNumberReader(fileReader);
            lineNumberReader.skip(Long.MAX_VALUE);
            lines = lineNumberReader.getLineNumber() + 1;
            fileReader.close();
            lineNumberReader.close();
            return lines;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return lines;
    }

    /**
     * 读取指定行到末尾的内容
     * @param file
     * @param lines
     * @return
     */
    public static String readTailContent(File file, long lines) {
        StringBuilder content =new StringBuilder();
        Stack<String> stack = new Stack<String>();
        try {
            // GB18030
            String chatset = JefConfiguration.get(LogConfigItem.LOG_FILE_CHATSET);
            ReversedLinesFileReader object = new ReversedLinesFileReader(file,Charset.forName(chatset));
            long counter = 0L;
            while(counter < lines) {
                // 对读取到的每一行进行压缩
                //String gunzip = StringCompressUtils.gzip(object.readLine() + '\n');
                //stack.push(gunzip);
                String ip = "";
                // 是否每行都添加主机ip
                if (JefConfiguration.getBoolean(LogConfigItem.LOG_ADD_ADDRESS, false)) {
                    ip = NetUtils.getLocalIp();
                    ip = ip + "|--|";
                }

                stack.push(ip + object.readLine() + "\r\n");
                counter ++;
            }
            long size = stack.size();
            for (long i=0; i<size; i++) {
                content.append(stack.pop());
                //content.append("'POST_GIRL'");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            stack = null;
        }
        return content.toString();
    }

    /**
     * 文件中追加内容
     * @param fileName
     * @param content
     */
    public static void writeFileByStreamByRandomAccess(String fileName, String content) {
        try {
            // 打开一个随机访问文件流，按读写方式
            RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");
            // 文件长度，字节数
            long fileLength = randomFile.length();
            long fileSize = fileLength;
            double size = Math.round(fileSize / 1024.0 / 1024.0 * 100) / 100.0;
            int splitSize = JefConfiguration.getInt(LogConfigItem.LOG_SPLIT_SIZE, 200);
            //System.out.println(splitSize + "当前文件大小" + size);
            if (size >= splitSize) {
                updateFileName(fileName);
                randomFile = new RandomAccessFile(fileName, "rw");
                fileLength = randomFile.length();
            }
            // 将写文件指针移到文件尾。
            randomFile.seek(fileLength);
            //randomFile.writeBytes(content + "\r\n");
            content = content + "\r\n";
            randomFile.write(content.getBytes("utf-8"));
            randomFile.close();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
    }

    public static void writeFileByStream(String fileName, String content) {
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(fileName, true)));
            out.write(content + "\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }

    }

    /**
     * 修改文件名
     * @param fileName
     */
    public static void updateFileName(String fileName) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));//设置北京时间
        String now = simpleDateFormat.format(new Date());
        String newFileName = fileName + now;

        File target = new File(newFileName);
        if (target.exists()) { //新文件若存在，则删掉
            target.delete();
        }
        File file = new File(fileName); // 旧文件
        boolean result = file.renameTo(target); //将旧文件更名
        if(result) {
            System.out.println("更名成功");

        } else { //更名失败，则采取变相的更名方法
            try{
                Files.copy(file.toPath(), target.toPath());
                //FileUtils.copyFile(file, target); // 将旧文件拷贝给新文件
                System.out.println("更名成功222");
                //清空旧文件
                emptyFileContent(file);
            } catch (IOException e) {
                System.out.println("更名失败");
                logger.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 清空文件内容
     * @param file
     */
    public static void emptyFileContent(File file) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file);
            out.write(new byte[0]);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            System.out.println("清空文件失败");
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static String decode(String str, String symbol) {

        String[] split = str.split(symbol);
        StringBuilder sb = new StringBuilder();
        try {
            for (String st : split) {
                sb.append(StringCompressUtils.gunzip(st));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}
